package net.maku.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.maku.framework.common.entity.WxUserInfoEntity;
import net.maku.framework.common.exception.ServerException;
import net.maku.framework.common.utils.WeiXinUtils;
import net.maku.framework.security.cache.TokenStoreCache;
import net.maku.framework.security.mobile.MemberAuthMobileToken;
import net.maku.framework.security.user.UserDetail;
import net.maku.member.entity.MemberUserEntity;
import net.maku.member.service.MemberUserService;
import net.maku.member.service.MemberUserTokenService;
import net.maku.member.vo.MemberUserTokenVO;
import net.maku.system.dao.SysOrgDao;
import net.maku.system.entity.SysOrgEntity;
import net.maku.system.params.CodeLoginParams;
import net.maku.system.params.QueryUserParams;
import net.maku.system.params.UnionLoginParams;
import net.maku.system.params.UpdateUserParams;
import net.maku.system.service.SysUserAuthService;
import net.maku.system.vo.LoginUserVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author Administrator
 */
@Service
@Slf4j
public class SysUserAuthServiceImpl implements SysUserAuthService {

    @Autowired
    private MemberUserService memberUserService;
    @Autowired
    private SysOrgDao sysOrgDao;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private MemberUserTokenService memberUserTokenService;
    @Autowired
    private TokenStoreCache tokenStoreCache;

    @Value("${wx.appId}")
    private String appId;
    @Value("${wx.appSecret}")
    private String appSecret;


    @Override
    public MemberUserTokenVO loginByCode(CodeLoginParams codeLoginParams) {
        String authPhoneCode = codeLoginParams.getAuthPhoneCode();
        String loginCode = codeLoginParams.getLoginCode();
        String userPhone = WeiXinUtils.getUserPhone(authPhoneCode, appId, appSecret);
        WxUserInfoEntity wxUserInfo = WeiXinUtils.getWxUserInfo(loginCode, appId, appSecret);
        if(wxUserInfo == null){
            throw new ServerException("获取用户信息失败");
        }
        if(StringUtils.isBlank(userPhone)){
            throw new ServerException("获取微信用户信息异常");
        }
        UnionLoginParams params = new UnionLoginParams();
        params.setMemberPhone(userPhone);
        params.setUnionId(wxUserInfo.getUnionId());
        return this.loginByUnionId(params);
    }

    @Override
    public MemberUserTokenVO loginByUnionId(UnionLoginParams unionLoginParams) {
        String unionId = unionLoginParams.getUnionId();
        String memberPhone = unionLoginParams.getMemberPhone();
        QueryWrapper<MemberUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile", memberPhone);
        MemberUserEntity memberUser = memberUserService.getOne(queryWrapper);
        //根据手机号查不到用户信息，则注册新的用户
        if(memberUser == null){
            MemberUserEntity userEntity = regUser(unionId, memberPhone);
        }else {
            //能够查询到手机号，
            String unionIdDb= memberUser.getUnionId();
            if(StringUtils.isBlank(unionIdDb)){
                MemberUserEntity update = new MemberUserEntity();
                update.setId(memberUser.getId());
                update.setUnionId(unionId);
                memberUserService.updateById(update);
            }
        }
        Authentication authentication = authenticationManager.authenticate(new MemberAuthMobileToken(memberPhone));
        // 用户信息
        UserDetail user = (UserDetail) authentication.getPrincipal();
        // 生成 accessToken
        MemberUserTokenVO memberUserTokenVO = memberUserTokenService.createToken(user.getId());
        // 保存用户信息到缓存
        tokenStoreCache.saveUser(memberUserTokenVO.getAccessToken(), user);
        return memberUserTokenVO;
    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginUserVo getUserInfoByCode(QueryUserParams codeLoginParams) {
        String loginCode = codeLoginParams.getLoginCode();
        WxUserInfoEntity wxUserInfo = WeiXinUtils.getWxUserInfo(loginCode, appId, appSecret);
        if(wxUserInfo == null){
            throw new ServerException("获取用户微信信息错误");
        }
        String authPhoneCode = codeLoginParams.getAuthPhoneCode();
        String userPhone = WeiXinUtils.getUserPhone(authPhoneCode, appId, appSecret);
        if(StringUtils.isBlank(userPhone)){
            throw new ServerException("获取用户手机错误");
        }
        QueryWrapper<MemberUserEntity> userQuery = new QueryWrapper<>();
        userQuery.eq("mobile",userPhone);
        MemberUserEntity userEntity = memberUserService.getOne(userQuery);
        //通过手机号查询到的会员信息
        if(userEntity == null){
            userEntity = regUser(wxUserInfo.getUnionId(), userPhone);
            return convert2LoginData(userEntity);
        }
        completeUserInfo(userEntity,wxUserInfo.getUnionId());
        return convert2LoginData(userEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginUserVo getUserInfoByUnionId(UnionLoginParams unionLoginParams) {
        String unionId = unionLoginParams.getUnionId();
        String memberPhone = unionLoginParams.getMemberPhone();
        QueryWrapper<MemberUserEntity> userQuery = new QueryWrapper<>();
        userQuery.eq("mobile",memberPhone);
        MemberUserEntity userEntity = memberUserService.getOne(userQuery);
        //通过手机号查询到的会员信息
        if(userEntity == null){
            MemberUserEntity regUser = regUser(unionId, memberPhone);
            return convert2LoginData(regUser);
        }
        completeUserInfo(userEntity,unionId);
        return convert2LoginData(userEntity);
    }

    @Override
    public void updateUserInfo(UpdateUserParams updateUserParams) {
        MemberUserEntity user = memberUserService.getById(updateUserParams.getId());
        if(user == null){
            return;
        }
        Long orgId = user.getOrgId();
        if(orgId !=null){
            return;
        }
        MemberUserEntity userEntity = BeanUtil.copyProperties(updateUserParams, MemberUserEntity.class);
        memberUserService.updateById(userEntity);
    }

    @Override
    public LoginUserVo getUserInfoByMobile(String mobile) {
        QueryWrapper<MemberUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile",mobile);
        MemberUserEntity one = memberUserService.getOne(queryWrapper);
        if(one == null){
            one = new MemberUserEntity();
            one.setMobile(mobile);
            LoginUserVo loginUserVo = BeanUtil.copyProperties(one, LoginUserVo.class);
            return loginUserVo;
        }
        LoginUserVo loginUserVo = BeanUtil.copyProperties(one, LoginUserVo.class);
        Long orgId = one.getOrgId();
        SysOrgEntity orgEntity = sysOrgDao.selectById(orgId);
        loginUserVo.setOrgName(orgEntity.getUnionAbbreviation());
        loginUserVo.setMemberId(one.getId());
        return loginUserVo;
    }


    /**
     * 将会员信息转换为登陆需要的数据
     * @param user
     */
    private LoginUserVo convert2LoginData(MemberUserEntity user) {
        LoginUserVo loginUserVo = BeanUtil.copyProperties(user, LoginUserVo.class);
        loginUserVo.setMemberId(user.getId());
        if(user.getOrgId() != null){
            SysOrgEntity orgEntity = sysOrgDao.selectById(user.getOrgId());
            loginUserVo.setOrgName(orgEntity.getUnionAbbreviation());
        }
        return loginUserVo;
    }

    /**
     * 会员表手机号存在的情况，unionId可能不没有，更新unionId；member_auth表中新增此手机号的授权登陆
     * @param userEntity
     * @param unionId
     */
    private void completeUserInfo(MemberUserEntity userEntity, String unionId) {
        String unionIdDb = userEntity.getUnionId();
        if(StringUtils.isBlank(unionIdDb)){
            MemberUserEntity update = new MemberUserEntity();
            update.setId(userEntity.getId());
            update.setUnionId(unionId);
            memberUserService.updateById(update);
        }
    }

    /**
     * 注册用户
     * @param unionId
     * @param phone
     */
    private MemberUserEntity regUser(String unionId,String phone){
        MemberUserEntity userEntity = new MemberUserEntity();
        userEntity.setUnionId(unionId);
        userEntity.setMobile(phone);
        //userEntity.setRealName("微信用户");
        userEntity.setDeleted(0);
        memberUserService.save(userEntity);
        return userEntity;
    }




}
